iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
自我挑戰組

馬克的軟體架構小筆記系列 第 21

30-21 之 Domain Layer - Lazy Load ( 未完成 )

  • 分享至 

  • xImage
  •  

什麼是 Lazy Load 呢 ?

An object that doesn’t contain all of the data you need but knows how to get it.

簡單的想你可以想成有一個很大的 Object S,然後裡面有 A、B、C 欄位,每個裡面都還是一個很大包的 Object,而 Lazy Load 就是可以在讀取 S.A 的資料時,可以只需要將 S.A 載入到記憶體,而不用整個 S 都要載入到記憶體中。

在書中有提到四種方式,然後右邊箭頭代表適用的模式 :

  • lazy initialization → active record、table data gateway、row data gateway
  • virtual proxy → data mapper
  • value holder → domain model
  • ghost → Identity Map

接下來由範例來說明每種模式的樣子。

每一次訪問屬性時,先判斷有沒有,如果為空,則在去 load 值。( 怎麼感覺好像 cache ),但這也代表要訪問屬性時,需要透過方法。

Inheritance → Lazy Loading 常見問題

多餘的資料庫處理 → ripple loading

This will cause you to go to the database once for each object instead of reading them all in at once.

範例

Lazy initialization

下面這個是書中的範例,但我第一眼看到時冒出兩個問題 :

  • 這感覺不就是 cache 嗎 ? 那如果 findForSupplier 的資料有更新怎麼辦 ?
  • 這範例感覺比較像 cache 吧 ? 感覺和 Lazy Loading 不要全部載入有點不太一樣呢 ?
class Supplier...
	public List getProducts() {
		if (products == null) products = Product.findForSupplier(getID()); 
    return products;
	}
}

然後又去找了其它的例如 wiki 的範例,我到覺得比較適合,雖然他和上面書中的範例有點相似,都是去記憶中拿,到這裡 new 物件的,事實上應該是不會隨這時間而變動,因此應該是不太會有像 cache 更新的問題。

class Fruit {

    private static Map<FruitType, Fruit> types = new HashMap<>();
    
    public static Fruit getFruitByTypeName(FruitType type) {
        Fruit fruit;
        if (!types.containsKey(type)) {
            // Lazy initialisation
            fruit = new Fruit(type);
            types.put(type, fruit);
        } else {
            // OK, it's available currently
            fruit = types.get(type);
        }
        
        return fruit;
    }
}

Virtual Proxy

這裡我用 js 簡單舉個例子,假設我們有多種產品,然後要根據產品類型產生相對應的物件,然後下面就有兩種寫法,一個是『 全載入 』而另一個就是『 需要那個才載入那個 』。

// 全載入,就算你只要用 COURSE 的方法
const ProductFactory = {
    'ARTICLE': require('./article')
    'COURSE': require('./course')
}

// Lazy Loading,當你需要的使後才 require 該物件
const ProductLazyLoadingFactory = new Proxy(
    {},
    {
      get: (target, prop) => {
        const product = _productFactory(prop)
        return product
      }
    }
  )

  function _productFactory (category) {
    switch (category) {
      case 'ARTICLE':
        return require('./article')
      case 'COURSE':
        return require('./course')
      default:
        throw new Error(`The category#${category} is nonexistent`)
    }
  }

小總結

這個知識點可以用來解釋什麼現象

這個知識點可以和以前的什麼知識連結呢 ?

我要如何運用這個知識點 ?

參考資料


上一篇
30-20 之 Domain Layer - UnitOfWork
下一篇
30-22 之 Remote Facade
系列文
馬克的軟體架構小筆記29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言